home *** CD-ROM | disk | FTP | other *** search
- /* GRAPHIC LISP */
- /* Scritto nel 1991-94 da Zoia Andrea Michele */
- /* Via Pergola #1 Tirano (SO) Tel. 0342-704210 */
- /* file closhash.c */
-
- #include "clos.h"
-
- /* gestione della HashTable */
-
- node *HashTable=NULL;
- hash_t MaxHash;
- hash_t HashAllocated;
- char Hash_buf1[MAX_ID_LENGHT+1];
-
- hash_t hash();
-
-
- hash_t hash(s)
- char *s;
- {
- /* NOTA: si suppone che sizeof(unsigned long int)=4byte(32 bit) */
- unsigned int i;
- unsigned long ret;
-
- ret=0L;
- for(i=0;s[i];i++){
- ret+=((unsigned long int)((unsigned char)s[i]))<<((i%16)<<1);
- }
- return (hash_t)ret%MaxHash; /* tra 0 e maxhash-1 */
- }
-
- node hash_search(s,nh)
- char *s;
- hash_t *nh;
- {
- /*
- se trova *s ritorna il nodo col nome corrispondente e
- nh viene settato al suo hash
- se non lo trova ritorna VOID e nh settato all'hash libero
- se hashtable e' piena salta a jumpbuf stampando l'errore HASHFULL
- NON bisogna chiamarla con s=NULL
- */
- int found_flag;
- hash_t found_hash;
- hash_t current;
- hash_t first;
-
- current=first=hash(s);
- found_flag=FALSE;
- for(;;){
- if(HashTable[(unsigned)current]==VOID){
- /* p punta ad un hash vuoto */
- /* vuol dire che s non e' stata tovata nella hastable */
- /* allora si guarda found_flag */
- /* se e' TRUE allora found_flag contiene il primo hash cancellato */
- /* che approssima meglio l'hash effettivo di s */
- /* se e' FALSE allora l'hash migliore e' proprio current */
-
- *nh=found_flag?found_hash:current;
-
- /* si ritorna VOID ad per indicare che la stringa s non e' stata trovata */
- /* ma che potrebbe essere messa nella posizione *nh */
-
- return VOID;
- }
- if(HashTable[(unsigned)current]==DELETED){
- /* se current e' cancellato allora ci si ricorda di questo hash */
- /* (se e' il primo trovato) dato che e' il migliore per la stringa s */
- if(!found_flag){
- found_hash=current;
- found_flag=TRUE;
- }
- }else{
- /* current punta ad un hash occupato */
-
- if(!strcmp(string_get(NAME(HashTable[(unsigned)current]),Hash_buf1),s)){
- /* ok rappresenta proprio il nodo di nome s */
- /* la procedura allora ritorna il nodo di nome s */
- /* e setta nh al valore dell'hash */
-
- *nh=current;
- return (node)HashTable[(unsigned)current];
- }
- }
- /* si incrementa circolarmente current */
- current=((++current)<MaxHash)?current:0;
-
- /* se current e' tornato ad essere uguale a first allora si e' */
- /* passata tutta la hashtable senza trovare la stringa s */
- if(current==first){
- if(found_flag){
- /* pero' l'hash cancellato lo si e' trovato */
- *nh=found_hash;
- return VOID;
- }
- /* l'hash table e' piena */
- error(E_HASHFULL,ERR_TCRIT|ERR_MERROR|ERR_PVOID,NULL);
- }
- }/* for(;;) */
- }
-
- void hash_put(n,h)
- node n;
- hash_t h;
- {
- /* inserisce il nodo n nella posizione h */
- HashTable[(unsigned)h]=n;
- HashAllocated++;
- }
-
- void hash_del(h)
- hash_t h;
- {
- /* rimuove la posizione h */
- HashTable[(unsigned)h]=DELETED;
- HashAllocated--;
- }
-
- int hash_malloc(h)
- lsiz_t h;
- {
- /* alloca la memoria per la hashtable */
- unsigned long int i;
-
- if(h*sizeof(node)>0xffffL) return ERROR;
-
- if((HashTable=(node *)malloc((unsigned)h*(unsigned)sizeof(node)))==NULL){
- HashTable=NULL;
- MaxHash=0L;
- return ERROR;
- }
- for(i=0;i<h;i++){
- HashTable[(unsigned)i]=VOID;
- }
- MaxHash=(hash_t)h;
- HashAllocated=(hash_t)0;
- return OK;
- }
-
- void hash_free()
- {
- if(HashTable)
- free(HashTable);
- HashTable=NULL;
- }
-
-
-
- void hash_stat()
- {
- /* stampa la hashtable su stderr */
- /* '-' hash vuoto ,'#' Allocato '=' cancellato */
-
- hash_t counter;
-
- for(counter=0;counter<MaxHash;counter++){
- if(HashTable[(unsigned)counter]==VOID){
- lisp_print_string(".",stderr);
- }else{
- if(HashTable[(unsigned)counter]==DELETED){
- lisp_print_string("*",stderr);
- }else{
- lisp_print_string("#",stderr);
- }
- }
- }
- lisp_print_string("\n",stderr);
- }
-
-
-
-